home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / pov / source / render.c < prev    next >
C/C++ Source or Header  |  1994-01-05  |  16KB  |  534 lines

  1. /****************************************************************************
  2. *                   render.c
  3. *
  4. *  This module implements the main raytracing loop.
  5. *
  6. * 08/07/92 lsk    Changed the normal antialiasing function to use a loop 
  7. *                 where the number of rays per pixel when antialiasing can 
  8. *                 be sepcified.
  9. *
  10. *  from Persistence of Vision Raytracer
  11. *  Copyright 1993 Persistence of Vision Team
  12. *---------------------------------------------------------------------------
  13. *  NOTICE: This source code file is provided so that users may experiment
  14. *  with enhancements to POV-Ray and to port the software to platforms other
  15. *  than those supported by the POV-Ray Team.  There are strict rules under
  16. *  which you are permitted to use this file.  The rules are in the file
  17. *  named POVLEGAL.DOC which should be distributed with this file. If
  18. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  19. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  20. *  Forum.  The latest version of POV-Ray may be found there as well.
  21. *
  22. * This program is based on the popular DKB raytracer version 2.12.
  23. * DKBTrace was originally written by David K. Buck.
  24. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  25. *
  26. ******************************************************************************/
  27.  
  28. #include "frame.h"
  29. #include "vector.h"
  30. #include "povproto.h"
  31.  
  32. extern FILE_HANDLE *Output_File_Handle;
  33. extern char Output_File_Name[FILE_NAME_LENGTH];
  34. extern char Input_File_Name[FILE_NAME_LENGTH];
  35. extern char Stat_File_Name[FILE_NAME_LENGTH];
  36. extern char OutputFormat, Color_Bits, PaletteOption;
  37. extern char VerboseFormat;
  38. extern unsigned int Options;
  39. extern int File_Buffer_Size;
  40. extern int Use_Slabs;
  41. volatile int Stop_Flag;
  42. extern int First_Line, Last_Line;
  43. extern int First_Column, Last_Column;
  44. extern long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  45. extern short *hashTable;
  46. extern unsigned short crctab[256];
  47. extern OBJECT *Root_Object;
  48. extern long AntialiasDepth;
  49. extern DBL JitterScale;
  50.  
  51. #define rand3d(a,b) crctab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
  52.  
  53. FRAME Frame;
  54. RAY *CM_Ray;
  55. int Trace_Level, SuperSampleCount;
  56.  
  57. DBL Max_Trace_Level = 5;
  58. DBL maxclr;
  59.  
  60. static void check_stats PARAMS((int y));
  61. static void do_anti_aliasing PARAMS((int x, int y, COLOUR *Colour));
  62. static void output_line PARAMS((int y));
  63.  
  64. COLOUR *Previous_Line, *Current_Line;
  65.  
  66. char *Previous_Line_Antialiased_Flags, *Current_Line_Antialiased_Flags;
  67. RAY Ray;
  68.  
  69. void Create_Ray (ray, width, height, x, y)
  70. RAY *ray;
  71. int width, height;
  72. DBL x, y;
  73.   {
  74.   register DBL X_Scalar, Y_Scalar;
  75.   VECTOR Temp_Vect_1, Temp_Vect_2;
  76.  
  77.   /* Convert the X Coordinate to be a DBL from 0.0 to 1.0 */
  78.   X_Scalar = (x - (DBL) width / 2.0) / (DBL) width;
  79.  
  80.   /* Convert the Y Coordinate to be a DBL from 0.0 to 1.0 */
  81.   Y_Scalar = (( (DBL)(Frame.Screen_Height - 1) - y) -
  82.     (DBL) height / 2.0) / (DBL) height;
  83.  
  84.   VScale (Temp_Vect_1, Frame.Camera->Up, Y_Scalar);
  85.   VScale (Temp_Vect_2, Frame.Camera->Right, X_Scalar);
  86.   VAdd (ray->Direction, Temp_Vect_1, Temp_Vect_2);
  87.   VAdd (ray->Direction, ray->Direction, Frame.Camera->Direction);
  88.   VNormalize (ray->Direction, ray->Direction);
  89.   Initialize_Ray_Containers (ray);
  90.   ray->Quadric_Constants_Cached = FALSE;
  91.   }
  92.  
  93. void Read_Rendered_Part()
  94.   {
  95.   int rc, x, line_number;
  96.   unsigned char Red, Green, Blue;
  97.   DBL grey;
  98.  
  99.   maxclr = (DBL)(1 << Color_Bits) - 1.0;
  100.   while ((rc = Read_Line(Output_File_Handle, Previous_Line, &line_number)) == 1) 
  101.     {
  102.     if (Options & DISPLAY)
  103.       for (x = 0 ; x < Frame.Screen_Width ; x++) 
  104.       {
  105.       if (PaletteOption == GREY) 
  106.         {
  107.         grey = Previous_Line[x].Red * 0.287 +
  108.         Previous_Line[x].Green * 0.589 +
  109.         Previous_Line[x].Blue * 0.114;
  110.         Red = Green = Blue = (unsigned char)(grey * maxclr);
  111.         }
  112.       else 
  113.         {
  114.         Red = (unsigned char) (Previous_Line[x].Red * maxclr);
  115.         Green = (unsigned char) (Previous_Line[x].Green * maxclr);
  116.         Blue = (unsigned char) (Previous_Line[x].Blue * maxclr);
  117.         }
  118.       display_plot (x, line_number, Red, Green, Blue);
  119.       COOPERATE     /* Moved inside loop JLN 12/91 */
  120.         }
  121.       }
  122.  
  123.     First_Line = line_number+1;
  124.  
  125.   if (rc == 0) 
  126.     {
  127.     Close_File(Output_File_Handle);
  128.     if (Open_File (Output_File_Handle, Output_File_Name,
  129.       &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
  130.       APPEND_MODE) != 1) 
  131.       {
  132.       fprintf (stderr, "Error opening output file\n");
  133.       fflush(stdout);
  134.       close_all();
  135.       exit(1);
  136.       }
  137.     return;
  138.     }
  139.  
  140.   fprintf (stderr, "Error reading aborted data file\n");
  141.   }
  142.  
  143. void Start_Tracing ()
  144.   {
  145.   COLOUR Colour;
  146.   register int x, y;
  147.   unsigned char Red, Green, Blue;
  148.   DBL grey;
  149.  
  150.   for (y = (Options & ANTIALIAS)?First_Line-1:First_Line; y<Last_Line; y++) 
  151.     {
  152.  
  153.     check_stats(y);
  154.  
  155.     for (x = First_Column ; x < Last_Column ; x++) 
  156.       {
  157.  
  158.       Check_User_Abort(1);
  159.       
  160.       Number_Of_Pixels++;
  161.  
  162.       Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height, (DBL) x, (DBL) y);
  163.       Trace_Level = 0;
  164.       Trace (&Ray, &Colour);
  165.       Clip_Colour (&Colour, &Colour);
  166.  
  167.       Current_Line[x] = Colour;
  168.  
  169.       if (Options & ANTIALIAS)      
  170.         do_anti_aliasing(x, y, &Colour); 
  171.  
  172.       if (y != First_Line-1) 
  173.         {
  174.  
  175.         if (PaletteOption == GREY) 
  176.           {
  177.           grey = Colour.Red * 0.287 +
  178.           Colour.Green * 0.589 +
  179.           Colour.Blue * 0.114;
  180.           Red = Green = Blue = (unsigned char)(grey * maxclr);
  181.           }
  182.         else 
  183.           {
  184.           Red = (unsigned char) (Colour.Red * maxclr);
  185.           Green = (unsigned char) (Colour.Green * maxclr);
  186.           Blue = (unsigned char) (Colour.Blue * maxclr);
  187.           }
  188.         if (Options & DISPLAY)
  189.           display_plot (x, y, Red, Green, Blue);
  190.         }
  191.       }
  192.     output_line(y);
  193.     }
  194.  
  195.   if (Options & DISKWRITE) 
  196.     {
  197.     if (Last_Line != First_Line)
  198.     Write_Line (Output_File_Handle, Previous_Line, Last_Line - 1);
  199.     }
  200.   }
  201.  
  202. static void check_stats(y)
  203. register int y;
  204.   {
  205.   FILE *stat_file;
  206.  
  207.   /* New verbose options CdW */
  208.   if (Options & VERBOSE && VerboseFormat=='0')
  209.     {
  210.     printf ("POV-Ray rendering %s to %s",Input_File_Name,Output_File_Name);
  211.     if((First_Line != 0) || (Last_Line != Frame.Screen_Height))
  212.       printf(" from %4d to %4d:\n",First_Line+1, Last_Line);
  213.     else
  214.       printf (":\n");
  215.     printf ("Res %4d X %4d. Calc line %4d of %4d",Frame.Screen_Width, Frame.Screen_Height, (y-First_Line)+1, Last_Line-First_Line);
  216.     if (!(Options & ANTIALIAS))
  217.       printf(".");
  218.     }
  219.   if (Options & VERBOSE_FILE)
  220.     {
  221.     stat_file = fopen(Stat_File_Name,"w+t");
  222.     fprintf (stat_file,"Line %4d.\n", y);
  223.     fclose(stat_file);
  224.     }
  225.  
  226.   /* Use -vO for Old style verbose */
  227.   if (Options & VERBOSE && (VerboseFormat=='O')) 
  228.     {
  229.     printf ("Line %4d", y);
  230.     }
  231.   if (Options & VERBOSE && VerboseFormat=='1')
  232.     {
  233.     fprintf (stderr,"Res %4d X %4d. Calc line %4d of %4d",Frame.Screen_Width, Frame.Screen_Height, (y-First_Line)+1, Last_Line-First_Line);
  234.     if (!(Options & ANTIALIAS))
  235.       fprintf(stderr,".");
  236.     }
  237.  
  238.   if (Options & ANTIALIAS)
  239.     SuperSampleCount = 0;
  240.   }
  241.  
  242. static void do_anti_aliasing(x, y, Colour)
  243. register int x, y;
  244. COLOUR *Colour;
  245.   {
  246.   char Antialias_Center_Flag = 0;
  247.  
  248.   Current_Line_Antialiased_Flags[x] = 0;
  249.  
  250.   if (x != 0) 
  251.     {
  252.     if (Colour_Distance (&Current_Line[x-1], &Current_Line[x])
  253.       >= Frame.Antialias_Threshold) 
  254.       {
  255.       Antialias_Center_Flag = 1;
  256.       if (!(Current_Line_Antialiased_Flags[x-1])) 
  257.         {
  258.         Supersample (&Current_Line[x-1],
  259.           x-1, y, Frame.Screen_Width, Frame.Screen_Height);
  260.         Current_Line_Antialiased_Flags[x-1] = 1;
  261.         SuperSampleCount++;
  262.         }
  263.       }
  264.     }
  265.  
  266.   if (y != First_Line-1) 
  267.     {
  268.     if (Colour_Distance (&Previous_Line[x], &Current_Line[x])
  269.       >= Frame.Antialias_Threshold) 
  270.       {
  271.       Antialias_Center_Flag = 1;
  272.       if (!(Previous_Line_Antialiased_Flags[x])) 
  273.         {
  274.         Supersample (&Previous_Line[x],
  275.           x, y-1, Frame.Screen_Width, Frame.Screen_Height);
  276.         Previous_Line_Antialiased_Flags[x] = 1;
  277.         SuperSampleCount++;
  278.         }
  279.       }
  280.     }
  281.  
  282.   if (Antialias_Center_Flag) 
  283.     {
  284.     Supersample (&Current_Line[x],
  285.       x, y, Frame.Screen_Width, Frame.Screen_Height);
  286.     Current_Line_Antialiased_Flags[x] = 1;
  287.     *Colour = Current_Line[x];
  288.     SuperSampleCount++;
  289.     }
  290.  
  291.   return;
  292.   }
  293.  
  294.  
  295. void Initialize_Renderer PARAMS((void))
  296.   {
  297.   register int i;
  298.  
  299.   CM_Ray = &Ray;
  300.  
  301.   maxclr = (DBL)(1 << Color_Bits) - 1.0;
  302.  
  303.   /* These malloc's are never freed! Why ? Need a Deinit_Renderer() ?*/
  304.   Previous_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  305.   Current_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
  306.  
  307.   for (i = 0 ; i <= Frame.Screen_Width ; i++) 
  308.     {
  309.     Previous_Line[i].Red = 0.0;
  310.     Previous_Line[i].Green = 0.0;
  311.     Previous_Line[i].Blue = 0.0;
  312.     Current_Line[i].Red = 0.0;
  313.     Current_Line[i].Green = 0.0;
  314.     Current_Line[i].Blue = 0.0;
  315.     }
  316.  
  317.   if (Options & ANTIALIAS) 
  318.     {
  319.     Previous_Line_Antialiased_Flags =
  320.     (char *) malloc (sizeof (char)*(Frame.Screen_Width + 1));
  321.     Current_Line_Antialiased_Flags =
  322.     (char *)  malloc (sizeof (char)*(Frame.Screen_Width + 1));
  323.  
  324.     for (i = 0 ; i <= Frame.Screen_Width ; i++) 
  325.       {
  326.       (Previous_Line_Antialiased_Flags)[i] = 0;
  327.       (Current_Line_Antialiased_Flags)[i] = 0;
  328.       }
  329.     }
  330.  
  331.   Ray.Initial = Frame.Camera->Location;
  332.   return;
  333.   }
  334.  
  335. static void output_line (y)
  336. register int y;
  337.   {
  338.   COLOUR *Temp_Colour_Ptr;
  339.   char *Temp_Char_Ptr;
  340.  
  341.   if (Options & DISKWRITE)
  342.     if (y > First_Line) 
  343.     {
  344.     Write_Line (Output_File_Handle, Previous_Line, y-1);
  345.     }
  346.  
  347.   if (Options & VERBOSE)
  348.     {
  349.     if (Options & ANTIALIAS && VerboseFormat != '1')
  350.       printf (" supersampled %d times.", SuperSampleCount);
  351.  
  352.     if (Options & ANTIALIAS && VerboseFormat == '1')
  353.       {
  354.       fprintf (stderr," supersampled %d times.", SuperSampleCount);
  355.  
  356.       }
  357.     if (VerboseFormat == '1')
  358.       fprintf (stderr,"\r");
  359.     else
  360.       fprintf (stderr,"\n");
  361.     }
  362.   Temp_Colour_Ptr = Previous_Line;
  363.   Previous_Line = Current_Line;
  364.   Current_Line = Temp_Colour_Ptr;
  365.  
  366.   Temp_Char_Ptr = Previous_Line_Antialiased_Flags;
  367.   Previous_Line_Antialiased_Flags = Current_Line_Antialiased_Flags;
  368.   Current_Line_Antialiased_Flags = Temp_Char_Ptr;
  369.  
  370.   return;
  371.   }
  372.  
  373. void Trace (Ray, Colour)
  374. RAY *Ray;
  375. COLOUR *Colour;
  376.   {
  377.   OBJECT *Object;
  378.   INTERSECTION Best_Intersection, New_Intersection;
  379.   register int Intersection_Found;
  380.  
  381.   COOPERATE
  382.   Number_Of_Rays++;
  383.   Make_Colour (Colour, 0.0, 0.0, 0.0);
  384.  
  385.   if (Trace_Level > (int) Max_Trace_Level) 
  386.     return;
  387.  
  388.   Intersection_Found = FALSE;
  389.   Best_Intersection.Depth = BOUND_HUGE;
  390.  
  391.     /* What objects does this ray intersect? */
  392.   if (!Use_Slabs)
  393.     for (Object = Frame.Objects ; 
  394.          Object != NULL ;
  395.          Object = Object -> Sibling) 
  396.     {
  397.     if (Intersection (&New_Intersection, Object, Ray))
  398.       if (New_Intersection.Depth < Best_Intersection.Depth) 
  399.         {
  400.         Best_Intersection = New_Intersection;
  401.         Intersection_Found = TRUE;
  402.         }
  403.     }
  404.   else
  405.     Intersection_Found = Bounds_Intersect(Root_Object, Ray,
  406.       &Best_Intersection,&Object);
  407.  
  408.   if (Intersection_Found)
  409.     Determine_Apparent_Colour (&Best_Intersection, Colour, Ray);
  410.   else
  411.     if (Frame.Fog_Distance > 0.0)
  412.       *Colour = Frame.Fog_Colour;
  413.     else
  414.       *Colour = Frame.Background_Colour;
  415.   }
  416.  
  417. /* exit with error if image not completed/user abort*/
  418. void Check_User_Abort (Do_Stats)
  419. int Do_Stats;
  420.   {
  421.   TEST_ABORT
  422.   if (Stop_Flag) 
  423.     {
  424.     close_all();
  425.     if (Do_Stats)
  426.       {
  427.       PRINT_STATS
  428.       }
  429.     exit(2);
  430.     }
  431.   }
  432.  
  433. /*---------------  Standard sampling in loop  -----------------------*/
  434.  
  435. unsigned short JRanges[] = {1,1,1,1,3,2,5,3,7,4}; /* LSK */
  436.  
  437. void Supersample (result, x, y, Width, Height)
  438. COLOUR *result;
  439. int x, y, Width, Height;
  440.   {
  441.   COLOUR colour;
  442.   register DBL dx, dy, Jitter_X, Jitter_Y;
  443.   register int Jitt_Offset;
  444.   unsigned char Red, Green, Blue;
  445.   int JRange;                               /* LSK */
  446.   int JSteps;                               /* LSK */
  447.   DBL JScale;                               /* LSK */
  448.   DBL JSize,JOffset;                        /* LSK */
  449.   int i,j;                                  /* LSK */
  450.  
  451.   dx = (DBL) x;                             /* LSK */
  452.   dy = (DBL) y;                             /* LSK */
  453.   Jitt_Offset = 10;
  454.  
  455.   Number_Of_Pixels_Supersampled++;
  456.  
  457.   Make_Colour (result, 0.0, 0.0, 0.0);
  458.  
  459.   if (AntialiasDepth>1)                                           /* LSK */
  460.     {                                                             /* LSK */
  461.     /* JSize is the size of the jitter scattering area */
  462.     JSize = 1.0/AntialiasDepth;                                   /* LSK */
  463.  
  464.     /* JOffset is the 'radius' of the jitter scatter area */
  465.     JOffset = JSize/2.0;                                        /* LSK */
  466.  
  467.     /* JSteps is either 1 or 2 depending on whether the number of samples
  468.         is odd or even. This is because the loop need to either run through
  469.         or over 0
  470.      */
  471.     JSteps = 2-(AntialiasDepth % 2);                              /* LSK */
  472.  
  473.     /* JRange is the range that the loop will run through. I couldn't
  474.         come up with a function describing the values, so I used an array
  475.         for 2x2 up to 9x9.
  476.      */
  477.     JRange = JRanges[AntialiasDepth];                             /* LSK */
  478.  
  479.     /* JScale is the scaling value for the color resulting from the
  480.         ray before adding to the resultant color
  481.      */
  482.     JScale = 1.0/(DBL)(AntialiasDepth*AntialiasDepth);              /* LSK */
  483.  
  484.     for (i= -JRange;i<=JRange;i+=JSteps)
  485.       for (j= -JRange;j<=JRange;j+=JSteps)
  486.       {
  487.       if (Options & JITTER)
  488.         {
  489.         Jitter_X = (rand3d(x+Jitt_Offset, y) & 0x7FFF) / 32768.0 * JSize - JOffset;
  490.         Jitt_Offset++;
  491.         Jitter_Y = (rand3d(x+Jitt_Offset, y) & 0x7FFF) / 32768.0 * JSize - JOffset;
  492.         Jitt_Offset++;
  493.         }
  494.       else
  495.         {
  496.         Jitter_X=Jitter_Y=0.0;
  497.         }
  498.       Jitter_X*=JitterScale;
  499.       Jitter_Y*=JitterScale;
  500.  
  501.       Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height,
  502.         dx + Jitter_X + i * JSize/JSteps,
  503.         dy + Jitter_Y + j * JSize/JSteps );
  504.  
  505.       Trace_Level = 0;
  506.       Trace (CM_Ray, &colour);
  507.       Clip_Colour (&colour, &colour);
  508.       Scale_Colour (&colour, &colour, JScale );
  509.       Add_Colour (result, result, &colour);
  510.  
  511.       }
  512.     }                                       /* LSK */
  513.   else   /* 1x1 specified! */
  514.     {
  515.     Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height,dx,dy );
  516.  
  517.     Trace_Level = 0;
  518.     Trace (CM_Ray, &colour);
  519.     Clip_Colour (&colour, &colour);
  520.     Add_Colour (result, result, &colour);
  521.     Jitt_Offset += 10;
  522.     }
  523.  
  524.   if ((y != First_Line - 1) && (Options & DISPLAY)) 
  525.     {
  526.     Red = (unsigned char)(result->Red * maxclr);
  527.     Green = (unsigned char)(result->Green * maxclr);
  528.     Blue = (unsigned char)(result->Blue * maxclr);
  529.     display_plot (x, y, Red, Green, Blue);
  530.     }
  531.  
  532.   }
  533.  
  534.